// hal_rcc.ixx
#pragma once

#include "stm32f4xx_hal.h"// HAL库头文件
namespace hal
{

    class rcc
    {
        static inline TIM_HandleTypeDef htim7;
    public:

        // 获取时基(TIM7)句柄
        static auto getTIMBaseHandler(){return &htim7;}

    };

    class systemClock
    {
        /**
     * @brief 切换到内部HSI时钟源
     * @note 使用16MHz内部RC振荡器，用于低功耗或紧急恢复
     */
        static void switchToHSI() noexcept
        {
            __disable_irq();

            // 启用并切换到HSI
            __HAL_RCC_HSI_ENABLE();
            while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET) {
            }
            __HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_HSI);
            while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_HSI) {
            }

            __enable_irq();
        }

        /**
     * @brief 切换到PLL时钟源
     * @note 需先正确配置PLL参数
     */
        static void switchToPLL() noexcept
        {
            __disable_irq();

            // 启用并切换到PLL
            __HAL_RCC_PLL_ENABLE();
            while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET) {
            }
            __HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_PLLCLK);
            while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK) {
            }

            __enable_irq();
        }

    public:
        /**
     * @brief 配置系统时钟至默认频率168MHz
     * @note 基于外部12MHz晶振，经过严格测试可稳定运行
     */
        static void defaultConfig() noexcept
        {
            // 启用HSI作为临时系统时钟
            __HAL_RCC_HSI_ENABLE();
            __HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_HSI);

            RCC_OscInitTypeDef osc = {};
            RCC_ClkInitTypeDef clk = {};

            // 配置电压调节器
            __HAL_RCC_PWR_CLK_ENABLE();
            HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

            // 配置HSE和PLL
            osc.OscillatorType = RCC_OSCILLATORTYPE_HSE;
            osc.HSEState = RCC_HSE_ON;
            osc.PLL.PLLState = RCC_PLL_ON;
            osc.PLL.PLLSource = RCC_PLLSOURCE_HSE;
            osc.PLL.PLLM = PLLM;
            osc.PLL.PLLN = PLLN;
            osc.PLL.PLLP = PLLP;
            osc.PLL.PLLQ = PLLQ;
            if (HAL_RCC_OscConfig(&osc) != HAL_OK) Error_Handler();

            // 配置时钟树
            clk.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
                            RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
            clk.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
            clk.AHBCLKDivider = RCC_SYSCLK_DIV1;
            clk.APB1CLKDivider = RCC_HCLK_DIV4;
            clk.APB2CLKDivider = RCC_HCLK_DIV2;
            if (HAL_RCC_ClockConfig(&clk, FLASH_LATENCY_5) != HAL_OK) Error_Handler();
        }

        /**
     * @brief 超频至216MHz
     * @warning 需确保散热条件良好，可能影响稳定性
     */
        static void overclock() noexcept
        {
            setFrequency(216);
        }


        /**
     * @brief 动态设置系统时钟频率
     * @param plln 锁相环倍频系数，实际频率 = (HSE/M)*N
     * @warning 错误参数可能导致系统不稳定
     */
        static void setFrequency(uint32_t plln) noexcept
        {
            // 设置FLASH等待周期
            const uint32_t latency = (plln <= 168) ? FLASH_LATENCY_5 : FLASH_LATENCY_7;
            __HAL_FLASH_SET_LATENCY(latency);

            // 配置电压调节器
            HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

            // 切换到HSI保证配置安全
            switchToHSI();

            // 禁用当前PLL
            __HAL_RCC_PLL_DISABLE();

            // 配置新的PLL参数
            RCC_OscInitTypeDef osc = {};
            osc.OscillatorType = RCC_OSCILLATORTYPE_HSE;
            osc.HSEState = RCC_HSE_ON;
            osc.PLL.PLLState = RCC_PLL_ON;
            osc.PLL.PLLSource = RCC_PLLSOURCE_HSE;
            osc.PLL.PLLM = PLLM;
            osc.PLL.PLLN = plln;
            osc.PLL.PLLP = PLLP;
            osc.PLL.PLLQ = PLLQ;

            if (HAL_RCC_OscConfig(&osc) != HAL_OK) Error_Handler();

            // 切换到新的PLL时钟
            switchToPLL();

            // 更新系统核心时钟
            SystemCoreClock = plln * 1000000;

            // 重新配置HAL滴答定时器
            HAL_InitTick(TICK_INT_PRIORITY);
        }

    private:
        // PLL固定配置参数
        static constexpr uint32_t PLLM = 6;// HSE分频系数
        static constexpr uint32_t PLLP = RCC_PLLP_DIV2;
        static constexpr uint32_t PLLQ = 4;
        static constexpr uint32_t PLLN = 168;
    };


}





